package com.bizdk.generator.service.impl;

import cn.hutool.core.text.NamingCase;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.bizdk.generator.common.exception.ServerException;
import com.bizdk.generator.common.page.PageResult;
import com.bizdk.generator.common.query.Query;
import com.bizdk.generator.core.GenUtils;
import com.bizdk.generator.core.GenDataSrc;
import com.bizdk.generator.core.template.TemplateLoderUtils;
import com.bizdk.generator.entity.gen.Table;
import com.bizdk.generator.entity.gen.TableColumn;
import com.bizdk.generator.mapper.TableMapper;
import com.bizdk.generator.enums.FormLayoutEnum;
import com.bizdk.generator.service.DatasrcService;
import com.bizdk.generator.service.TableColumnService;
import com.bizdk.generator.service.TableService;
import lombok.AllArgsConstructor;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.sql.SQLException;
import java.util.Arrays;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.function.Function;
import java.util.stream.Collectors;


/**
 * 数据表
 */
@Service
@AllArgsConstructor
public class TableServiceImpl extends ServiceImpl<TableMapper, Table> implements TableService {
    
    private final TableColumnService columnService;
    
    private final DatasrcService datasrcService;
    
    private final TemplateLoderUtils generatorConfig;
    
    @Override
    public PageResult<Table> page(Query query) {
        IPage<Table> page = baseMapper.selectPage(new Page<>(query.getPageNum(), query.getPageSize()), query.getWrapper());
        return new PageResult<>(page.getRecords(), page.getTotal());
    }
    
    @Override
    public Table getByTableName(String tableName) {
        LambdaQueryWrapper<Table> queryWrapper = Wrappers.lambdaQuery();
        return baseMapper.selectOne(queryWrapper.eq(Table::getTableName, tableName));
    }
    
    @Transactional
    @Override
    public boolean updateById(Table entity) {
        super.updateById(entity);
        for (TableColumn column : entity.getColumns()) {
            columnService.updateById(column);
        }
        return true;
    }
    
    @Override
    @Transactional(rollbackFor = Exception.class)
    public void deleteBatchIds(Long[] ids) {
        // 删除表
        baseMapper.deleteBatchIds(Arrays.asList(ids));
        
        // 删除列
        columnService.deleteBatchTableIds(ids);
    }
    
    @Override
    @Transactional(rollbackFor = Exception.class)
    public void tableImport(Long datasrcId, String tableName) {
        GenDataSrc genDataSrc = null;
        try {
            // 初始化配置信息
            genDataSrc = datasrcService.get(datasrcId);
            // 查询表是否存在
            Table table = this.getByTableName(tableName);
            // 表存在
            if (table != null) {
                throw new ServerException(tableName + "已存在");
            }
            
            // 从数据库获取表信息
            table = GenUtils.getTable(genDataSrc, tableName);
            
            // 保存表信息
            table.setFormLayout(FormLayoutEnum.ONE.getValue());
            table.setBeanName(NamingCase.toPascalCase(tableName));
            table.setCreateTime(new Date());
            this.save(table);
            
            // 获取原生字段数据
            List<TableColumn> columnEntityList = GenUtils.getTableColumnList(genDataSrc, table.getId(),
                    table.getTableName());
            // 初始化字段数据
            columnService.initColumnList(columnEntityList);
            
            // 保存列数据
            columnEntityList.forEach(columnService::save);
        } finally {
            if (null != genDataSrc && null != genDataSrc.getConnection()) {
                try {
                    //释放数据源
                    genDataSrc.getConnection().close();
                } catch (SQLException e) {
                    log.error(e.getMessage(), e);
                }
            }
        }
    }
    
    @Override
    @Transactional(rollbackFor = Exception.class)
    public void sync(Long tableId) {
        Table table = this.getById(tableId);
        GenDataSrc genDataSrc = null;
        try {
            // 初始化配置信息
            genDataSrc = datasrcService.get(table.getDatasrcId());
            
            // 从数据库获取表字段列表
            List<TableColumn> columns = GenUtils.getTableColumnList(genDataSrc, table.getId(), table.getTableName());
            if (columns.size() == 0) {
                throw new ServerException("同步失败，请检查数据库表：" + table.getTableName());
            }
            
            List<String> dbTableColumnNameList = columns.stream().map(TableColumn::getColumnName)
                    .collect(Collectors.toList());
            
            // 表字段列表
            List<TableColumn> columnEntityList = columnService.getByTableId(tableId);
            
            Map<String, TableColumn> tableFieldMap = columnEntityList.stream()
                    .collect(Collectors.toMap(TableColumn::getColumnName, Function.identity()));
            
            // 初始化字段数据
            columnService.initColumnList(columns);
            
            // 同步表结构字段
            columns.forEach(column -> {
                // 新增字段
                if (!tableFieldMap.containsKey(column.getColumnName())) {
                    columnService.save(column);
                    return;
                }
                
                // 修改字段
                TableColumn tableColumn = tableFieldMap.get(column.getColumnName());
                tableColumn.setPkItem(column.isPkItem());
                tableColumn.setColumnComment(column.getColumnComment());
                tableColumn.setColumnType(column.getColumnType());
                tableColumn.setAttrType(column.getAttrType());
                
                columnService.updateById(tableColumn);
            });
            
            // 删除数据库表中没有的字段
            List<TableColumn> delFieldList = columnEntityList.stream()
                    .filter(field -> !dbTableColumnNameList.contains(field.getColumnName()))
                    .collect(Collectors.toList());
            if (delFieldList.size() > 0) {
                List<Long> fieldIds = delFieldList.stream().map(TableColumn::getId).collect(Collectors.toList());
                columnService.removeBatchByIds(fieldIds);
            }
        } finally {
            if (null != genDataSrc && null != genDataSrc.getConnection()) {
                try {
                    //释放数据源
                    genDataSrc.getConnection().close();
                } catch (SQLException e) {
                    log.error(e.getMessage(), e);
                }
            }
        }
    }
    
    @Override
    public List<Table> tableList(Long datasrcId) {
        GenDataSrc genDataSrc = null;
        // 初始化配置信息
        genDataSrc = datasrcService.get(datasrcId);
        GenUtils.getTableList(genDataSrc);
        return null;
    }
}